package com.link.base.base.buryingpoint.buriedcode.service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.link.base.base.shorturl.model.ShortURL;
import com.link.base.base.shorturl.service.ShortURLService;
import com.link.core.cllog.LCLogger;
import com.link.core.kafka.KafkaTemplateFacotry;
import com.link.core.kafka.conf.KafkaEnv;
import com.link.core.basic.service.KeyGenerateService;
import com.link.core.util.LovUtil;
import com.link.core.util.StringUtils;
import com.link.base.base.buryingpoint.buriedcode.model.BuriedCode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;
import com.link.base.base.buryingpoint.buriedcode.dao.mybatis.mapper.BuriedCodeMapper;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.BasicServiceImpl;
import sun.misc.BASE64Decoder;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 埋点代码-埋点代码
 *
 * @author 秦学刚
 * @date 2019/02/26 09:30
 */
@Service
public class BuriedCodeServiceImpl extends BasicServiceImpl<BuriedCode> implements BuriedCodeService {
    private static final Logger logger = LogManager.getLogger(BuriedCodeServiceImpl.class);

    @Resource
    private KeyGenerateService keyGenerateService;

    @Resource
    private ShortURLService shortURLService;

    @Resource
    private BuriedCodeMapper buriedCodeMapper;

    @Override
    public BasicMapper<BuriedCode> getBasicMapper() {
        return buriedCodeMapper;
    }

    private static final String BURIED_TOPIC = "KT_BURY";

    @Override
    public void beforUpsert(BuriedCode entity) throws Exception {
        if ("event".equalsIgnoreCase(entity.getType())) {
            String generateBuriedCode = decode(entity.getGenerateBuriedCode());
            entity.setGenerateBuriedCode(generateBuriedCode);
        } else {
            /* 对于广告链接埋点，把原始链接保存到短URL表,
            url id设置到埋点记录，访问时使用短URL，由于记录不会更改，所以不考虑修改链接的情况,
            attr1 放置短url前缀
             */
            if (entity.getShortUrlId() == null && StringUtils.isNotBlank(entity.getAttr1())) {
                Long shortUrlId = keyGenerateService.keyGenerate();
                ShortURL shortUrl = new ShortURL();
                shortUrl.setId(shortUrlId);
                shortUrl.setName(entity.getName());
                shortUrl.setModule("BuriedCode");
                shortUrl.setComments(entity.getAdvertisementName());
                shortUrl.setOriginURL(entity.getGenerateBuriedCode());
                shortURLService.insert(shortUrl);
                entity.setShortUrlId(shortUrlId);
                entity.setGenerateBuriedCode(entity.getAttr1() + shortUrlId);
            }
        }
    }

    /**
     * 字符串解密，采用BASE64的算法
     * @param encoder 需要解密的字符串
     * @return 解密后的字符串
     */
    public static final String decode(String encoder) throws Exception {
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] buf = decoder.decodeBuffer(encoder);
            return new String(buf, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new Exception(e.getMessage());
        }
    }

    /**
     * 批量下载埋点信息内容
     *
     * @param list 埋点信息list
     * @author : 秦学刚
     * @date: 2019/3/7 17:53
     */
    @Override
    public String batchBuriedDownLoad(List<BuriedCode> list) throws Exception {
        StringBuffer sb = new StringBuffer();
        try {
            if ("ground".equals(list.get(0).getType())) { // 广告链接埋点
                sb.append("1.URL获取");
                //sb.append(System.getProperty("line.separator"));
                //sb.append("  1. 请将生成的广告跟踪链接投放到对应的投放渠道中。");
                BuriedCode example = new BuriedCode();
                for (int i = 0; list != null && i < list.size(); i++) {
                    if ("ground".equals(list.get(i).getType())) { // 广告链接埋点
                        // 链接埋点数据保存前已被更改，并非前端传来数据，所以重新查询
                        BuriedCode result = list.get(i);
                        if (list.get(i).getShortUrlId() != null) {
                            example.setId(list.get(i).getId());
                            BuriedCode resultNew = queryById(example);
                            result = resultNew != null ? resultNew : result;
                        }

                        sb.append(System.getProperty("line.separator") + "\t");
                        sb.append("  投放渠道：" + LovUtil.getLovName("DELIVERY_CHANNEL", result.getDeliveryChannel()));
                        sb.append(System.getProperty("line.separator") + "\t");
                        sb.append("  " + result.getGenerateBuriedCode());
                    }
                }
                sb.append(System.getProperty("line.separator") + "\t");
                sb.append("2.URL投放说明");
                sb.append(System.getProperty("line.separator") + "\t");
                sb.append("  " + list.get(0).getInstallInstructions());
                //sb.append(System.getProperty("line.separator"));
                //sb.append("3.备注");
                //sb.append(System.getProperty("line.separator"));
                //sb.append("  " + list.get(0).getRemarks());
            } else {
                sb.append("1.代码获取");
                sb.append(System.getProperty("line.separator") + "\t");
                if ("event".equals(list.get(0).getType())) { // 广告链接埋点
                    sb.append(System.getProperty("line.separator") + "\t");
                    sb.append("  " + list.get(0).getGenerateBuriedCode());
                }
                sb.append(System.getProperty("line.separator") + "\t");
                sb.append("2.代码安装说明");
                sb.append(System.getProperty("line.separator") + "\t");
                sb.append("  " + list.get(0).getInstallInstructions());
                //sb.append(System.getProperty("line.separator"));
                //sb.append("3.备注");
                //sb.append(System.getProperty("line.separator"));
                //sb.append("  " + list.get(0).getRemarks());
            }
        } catch (Exception e) {
            LCLogger.withException(e);
            throw new Exception("下载埋点内容失败");
        }
        return sb.toString();
    }

    /**
     * 使用kafka保存埋点信息内容
     *
     * @author : 秦学刚
     * @param json 埋点信息json串
     * @date: 2019/3/7 17:53
     */

    @Override
    public void batchBuriedInsert(String json, HttpServletRequest request) throws Exception {
        boolean flag = KafkaEnv.isEnabled();
        JsonParser parser = new JsonParser();  //创建JSON解析器
        JsonObject jsonObject = (JsonObject) parser.parse(json);  //创建JsonObject对象
        String ip = getIpAddr(request);
        jsonObject.addProperty("$ip", ip);
        if (flag) {
            try {
                KafkaTemplateFacotry.send(BURIED_TOPIC, jsonObject.toString());
            } catch (Exception e) {
                KafkaEnv.setEnabled(false);
                logger.error(e.getMessage());
            }
        } else {
            logger.info("kafka server is not avilabel!");
        }
    }

    /**
     * 获取IP地址.
     * @author : 秦学刚
     * @param request HTTP请求.
     * @date: 2019/3/7 17:53
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}

